package com.piece.core.framework.util.file;

import com.piece.core.framework.util.net.HttpUtil;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Coordinate;
import net.coobird.thumbnailator.geometry.Position;
import net.coobird.thumbnailator.geometry.Positions;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;

/**
 * 图片工具类
 */
public class ImageUtil {

    /***
     * 剪裁图片
     *
     * @param inputStream 文件流
     * @param x  起点横坐标
     * @param y  纵坐标
     * @param w  长
     * @param h  高
     * @param prefix 图片后缀
     */
    public static BufferedImage cutImage(InputStream inputStream, int x, int y, int w, int h, String prefix) throws Exception {
        Iterator iterator = ImageIO.getImageReadersByFormatName(prefix);
        ImageReader reader = (ImageReader) iterator.next();
        // 转换成输入流
        ImageInputStream iis = ImageIO.createImageInputStream(inputStream);
        reader.setInput(iis, true);
        ImageReadParam param = reader.getDefaultReadParam();
        Rectangle rect = null;
        try {
            int width = reader.getWidth(0);
            int height = reader.getHeight(0);
            w = w == -1 ? width : w;
            h = h == -1 ? height : h;
            rect = null;
            if (w >= width || h >= height) {
                rect = new Rectangle(width, height);
            } else {
                rect = new Rectangle(x, y, w, h);
            }
        } catch (IOException e) {
            rect = new Rectangle(x, y, w, h);
        }
        param.setSourceRegion(rect);
        BufferedImage bi = reader.read(0, param);
        return bi;
    }

    /***
     * 图片旋转
     *
     * @param image    图像
     * @param degree   旋转角度
     */
    public static BufferedImage rotateImage(BufferedImage image, int degree) throws Exception {
        int w = image.getWidth();
        int h = image.getHeight();
        int type = image.getColorModel().getTransparency();
        BufferedImage img;
        Graphics2D graphics2d;
        (graphics2d = (img = new BufferedImage(w, h, type))
                .createGraphics()).setRenderingHint(
                RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2d.setPaint(Color.WHITE);
        graphics2d.fillRect(0, 0, w, h);
        graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);
        graphics2d.drawImage(image, 0, 0, Color.WHITE, null);
        graphics2d.dispose();
        return img;
    }

    /**
     * 剪切图片
     *
     * @param fileName 文件名
     * @param inputStream 文件流
     * @param avatar_data
     */
    public static InputStream cropImage(String fileName, InputStream inputStream, String avatar_data) throws Exception {
        // 获取图片后缀
        String prefix = FileUtil.getFileSuffix(fileName);
        String[] str = avatar_data.split(",");
        // 获取截取的x坐标
        int x = (int) Math.floor(Double.parseDouble(str[0].split(":")[1]));
        // 获取截取的y坐标
        int y = (int) Math.floor(Double.parseDouble(str[1].split(":")[1]));
        // 获取截取的高度
        int h = (int) Math.floor(Double.parseDouble(str[2].split(":")[1]));
        // 获取截取的宽度
        int w = (int) Math.floor(Double.parseDouble(str[3].split(":")[1]));
        // 获取旋转的角度
        int r = Integer.parseInt(str[4].split(":")[1].replaceAll("}", ""));
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            out = new ByteArrayOutputStream();
            BufferedImage cutImage = ImageUtil.cutImage(inputStream, x, y, w, h, prefix);
            BufferedImage rotateImage = ImageUtil.rotateImage(cutImage, r);
            ImageIO.write(rotateImage, prefix, out);
            // 转换后存入数据库
            byte[] b = out.toByteArray();
            in = new ByteArrayInputStream(b);
        } catch (Exception e) {
            throw new RuntimeException("图片裁剪错误: " + e.getMessage());
        } finally {
            if (null != out) {
                out.close();
            }
            return in;
        }
    }

    /**
     * 图片格式转换
     *
     * @param is         文件流
     * @param suffixName 转换图片格式
     * @throws IOException
     */
    public static byte[] format(InputStream is, String suffixName) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        Thumbnails.of(is).outputFormat(suffixName).toOutputStream(output);
        return output.toByteArray();
    }

    /**
     * 压缩文件
     *
     * @param file   原始文件
     * @param width  压缩后的宽度
     * @param height 压缩后的高度
     */
    public static byte[] scale(File file, int width, int height) throws IOException {
        return scale(Thumbnails.of(file), width, height);
    }

    /**
     * 压缩图片
     *
     * @param is     原图文件
     * @param width  压缩后的宽度
     * @param height 压缩后的高度
     */
    public static byte[] scale(InputStream is, int width, int height) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        Thumbnails.of(is).size(width, height).toOutputStream(output);
        return output.toByteArray();
    }

    /**
     * 压缩图片
     *
     * @param file    原始文件
     * @param maxSize 压缩后最大边长
     */
    public static byte[] scale(File file, int maxSize) throws IOException {
        return scale(file, maxSize, maxSize);
    }

    /**
     * 压缩图片
     *
     * @param is      原图文件
     * @param maxSize 压缩后最大边长
     */
    public static byte[] scale(InputStream is, int maxSize) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        Thumbnails.of(is).width(maxSize).toOutputStream(output);
        return output.toByteArray();
    }

    /**
     * 压缩图片,各边按比例压缩
     *
     * @param width  压缩后的宽度
     * @param height 压缩后的高度
     */
    public static <T> byte[] scale(Thumbnails.Builder<T> builder, int width, int height) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        builder.size(width, height).toOutputStream(output);
        return output.toByteArray();
    }

    public static byte[] screenShot(File file, int x, int y, int width, int height) throws Exception {
        return screenShot(Thumbnails.of(file), new Coordinate(x, y), width, height, FileUtil.getFileSuffix(file.getName()));
    }

    public static byte[] screenShot(File file, int x, int y, int size) throws Exception {
        return screenShot(file, x, y, size, size);
    }

    public static byte[] screenShot(File file, int width, int height) throws Exception {
        return screenShot(Thumbnails.of(file), Positions.CENTER, width, height, FileUtil.getFileSuffix(file.getName()));
    }

    public static byte[] screenShot(String fileName, InputStream inputStream, int x, int y, int width, int height) throws Exception {
        return screenShot(Thumbnails.of(inputStream), new Coordinate(x, y), width, height, FileUtil.getFileSuffix(fileName));
    }

    public static byte[] screenShot(String fileName, InputStream inputStream, int x, int y, int size) throws Exception {
        return screenShot(fileName, inputStream, x, y, size, size);
    }

    public static byte[] screenShot(String fileName, InputStream inputStream, int width, int height) throws IOException {
        return screenShot(Thumbnails.of(inputStream), Positions.CENTER, width, height, FileUtil.getFileSuffix(fileName));
    }

    /**
     * 截图
     */
    public static <T> byte[] screenShot(Thumbnails.Builder<T> builder, Position position, int width, int height, String prefix) throws IOException {
        BufferedImage image = builder.size(width, height).asBufferedImage();
        image = Thumbnails.of(image).size(width, height).crop(position).asBufferedImage();
        return toByte(image, prefix);
    }

    private static byte[] toByte(BufferedImage image, String prefix) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        ImageIO.write(image, prefix, output);
        output.flush();
        byte[] bytes = output.toByteArray();
        output.close();
        return bytes;
    }

    /**
     * 下载图片
     */
    public static byte[] download(String urlString) throws Exception {
        BufferedInputStream in = new BufferedInputStream(HttpUtil.get(urlString).execute().download());
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        Thumbnails.of(in).toOutputStream(output);
        return output.toByteArray();
    }

    /**
     * 下载压缩图片
     */
    public static byte[] download(String urlString, int maxSize) throws Exception {
        BufferedInputStream in = new BufferedInputStream(HttpUtil.get(urlString).execute().download());
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        Thumbnails.of(in).width(maxSize).toOutputStream(output);
        return output.toByteArray();
    }
}
